include(CheckLinkerFlag)

function(add_compiler_option_to_target_type TARGET BUILDTYPE VISIBILITY OPTIONS)
  include(CheckCCompilerFlag)
  list(APPEND OPTIONS ${ARGN})
  foreach(COMPILE_OPTION IN LISTS OPTIONS)
    string(REPLACE "=" "-" COMPILE_OPTION_NAME "${COMPILE_OPTION}")
    check_c_compiler_flag(${COMPILE_OPTION} "compiler_has${COMPILE_OPTION_NAME}")
    if (${compiler_has${COMPILE_OPTION_NAME}})
      target_compile_options(${TARGET} ${VISIBILITY}
        $<$<CONFIG:${BUILDTYPE}>:${COMPILE_OPTION}>)
    endif()
  endforeach()
endfunction()

function(add_compiler_option_to_all_but_target_type TARGET BUILDTYPE VISIBILITY OPTIONS)
  include(CheckCCompilerFlag)
  list(APPEND OPTIONS ${ARGN})
  foreach(COMPILE_OPTION IN LISTS OPTIONS)
    string(REPLACE "=" "-" COMPILE_OPTION_NAME "${COMPILE_OPTION}")
    check_c_compiler_flag(${COMPILE_OPTION} "compiler_has${COMPILE_OPTION_NAME}")
    if (${compiler_has${COMPILE_OPTION_NAME}})
      target_compile_options(${TARGET} ${VISIBILITY}
        $<$<NOT:$<CONFIG:${BUILDTYPE}>>:${COMPILE_OPTION}>)
    endif()
  endforeach()
endfunction()

function(add_linker_option_to_target_type TARGET BUILDTYPE VISIBILITY OPTIONS)
  include(CheckCCompilerFlag)
  list(APPEND OPTIONS ${ARGN})
  foreach(LINK_OPTION IN LISTS OPTIONS)
    string(REPLACE "," "_" LINK_OPTION_NAME "${LINK_OPTION}")
    check_linker_flag(C "${LINK_OPTION}" "linker_has${LINK_OPTION_NAME}")
    if (${linker_has${LINK_OPTION_NAME}})
      target_link_libraries(${TARGET} ${VISIBILITY}
        $<$<CONFIG:${BUILDTYPE}>:${LINK_OPTION}>)
    endif()
  endforeach()
endfunction()

function(add_linker_option_to_all_but_target_type TARGET BUILDTYPE VISIBILITY OPTIONS)
  include(CheckCCompilerFlag)
  list(APPEND OPTIONS ${ARGN})
  foreach(LINK_OPTION IN LISTS OPTIONS)
    string(REPLACE "," "_" LINK_OPTION_NAME "${LINK_OPTION}")
    check_linker_flag(C "${LINK_OPTION}" "linker_has${LINK_OPTION_NAME}")
    if (${linker_has${LINK_OPTION_NAME}})
      target_link_libraries(${TARGET} ${VISIBILITY}
        $<$<NOT:$<CONFIG:${BUILDTYPE}>>:${LINK_OPTION}>)
    endif()
  endforeach()
endfunction()

function(add_sanitizers_to_target TARGET BUILDTYPE VISIBILITY SANITIZERS)
  list(APPEND SANITIZERS ${ARGN})
  foreach(SAN IN LISTS SANITIZERS)
    set(CMAKE_REQUIRED_FLAGS "-fsanitize=${SAN}")
    check_c_compiler_flag("-fsanitize=${SAN}" "sanitizer-${SAN}-available")
    unset(CMAKE_REQUIRED_FLAGS)
    if (${sanitizer-${SAN}-available})
      list(APPEND AVAILABLE_SANITIZERS ${SAN})
    endif()
  endforeach()
  foreach(SAN IN LISTS AVAILABLE_SANITIZERS)
    target_compile_options(${TARGET} ${VISIBILITY} $<$<CONFIG:${BUILDTYPE}>:-fsanitize=${SAN}>)
    target_link_libraries(${TARGET} ${VISIBILITY} $<$<CONFIG:${BUILDTYPE}>:-fsanitize=${SAN}>)
  endforeach()
endfunction()
